<html>
    <head>
        <title>Itowns - Orientation utils example in globe</title>

        <meta charset="UTF-8">
        <link rel="stylesheet" type="text/css" href="css/example.css">
        <link rel="stylesheet" type="text/css" href="css/loading_screen.css">

        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <script src="js/GUI/dat.gui/dat.gui.min.js"></script>
    </head>
    <body>
        <div id="viewerDiv"></div>
        <script src="js/GUI/GuiTools.js"></script>
        <script src="../dist/itowns.js"></script>
        <script src="js/proj4defs/2154.js"></script>
        <script src="js/loading_screen.js"></script>
        <script src="js/ThreeLoader.js"></script>
        <script src="../dist/debug.js"></script>
        <script type="text/javascript">

            // Define initial camera position
            // Coordinate can be found on https://www.geoportail.gouv.fr/carte
            // setting is "coordonnée geographiques en degres decimaux"
            var positionOnGlobe = { longitude: 2.3345, latitude: 48.8504, altitude: 100 };

            // `viewerDiv` will contain iTowns' rendering area (`<canvas>`)
            var viewerDiv = document.getElementById('viewerDiv');

            // Instanciate iTowns GlobeView
            var view = new itowns.GlobeView(viewerDiv, positionOnGlobe, {
                handleCollision: false,
            });
           view.controls.minDistance = 30;

            var menuGlobe = new GuiTools('menuDiv', view);

            setupLoadingScreen(viewerDiv, view);

            // Add one imagery layer to the scene
            itowns.Fetcher.json('./layers/JSONLayers/Ortho.json').then(function _(config) {
                config.source = new itowns.WMTSSource(config.source);
                var layer = new itowns.ColorLayer('Ortho', config);
                view.addLayer(layer).then(menuGlobe.addLayerGUI.bind(menuGlobe));
            });

            // Add elevation layer.
            var promises = [];
            promises.push(itowns.Fetcher.json('./layers/JSONLayers/IGN_MNT_HIGHRES.json').then(function _(config) {
                config.source = new itowns.WMTSSource(config.source);
                var layer = new itowns.ElevationLayer(config.id, config);
                return view.addLayer(layer);
            }));

            // Input data : a geoJson file, with point features, with orientation specific properties
            var panoramics = 'https://raw.githubusercontent.com/iTowns/iTowns2-sample-data/master/immersive/exampleParis1/panoramicsMetaDataParis.geojson';
            var layer = {
                crsOut: view.referenceCrs,
                mergeFeatures: false,
                onGround: false,
            };

            // Add a promise to load oriented point datas
            promises.push(
                // first parse the JSON format
                itowns.Fetcher.json(panoramics, {})
                // then get geographic informations (coordinates) using GeoJson parser
                .then(function parseGeoJSON(orientations) { return itowns.GeoJsonParser.parse(orientations, layer);})
            );

            // load collada model of a renault trafic
            promises.push(ThreeLoader.load('Collada',
             'https://raw.githubusercontent.com/iTowns/iTowns2-sample-data/master/models/collada/renault_trafic_no_texture.dae')
             .then(function prepareModel(collada) {
                // prepare collada model base scale and rotation. in this example, we want the car to go straigth.
                var colladaModel = collada.scene;
                colladaModel.scale.set(0.5, 0.5, 0.5);
                colladaModel.rotateZ(-Math.PI / 2 );
                // put the model in a group, to allow user to do other transformation (rotation..)
                var group = new itowns.THREE.Group();
                group.add(colladaModel);
                return group;
             }));

            var onGround = false;

            // Load camera calibrations
            var calibrations = 'https://raw.githubusercontent.com/iTowns/iTowns2-sample-data/master/immersive/exampleParis1/cameraCalibration.json';
            
            // Use the cameraCalibrationParser to create OrientedImageCamera from camera calibration description file.
            promises.push(
                itowns.Fetcher.json(calibrations, {})
                .then(calibrations => itowns.CameraCalibrationParser.parse(calibrations, {near: 0.3, far: 0.6,}))
            );

            // wait for all layer to be loaded, we need for elevation layer
            view.addEventListener(itowns.GLOBE_VIEW_EVENTS.GLOBE_INITIALIZED, function init() {

                // wait for all the promises
                Promise.all(promises).then(function loadFeaturesModel(res) { loadFeatures(res[1], res[2], res[3]);});

                view.controls.setTilt(20, true);
            })


            // place a 3d model oriented for each feature
            function loadFeatures(points, colladaModel, cameras) {

                for (var feature of points.features) {

                    // clone the collada model
                    var model = colladaModel.clone();

                    var vertices = feature.vertices;
                    // get coordinate from point feature
                    var coord = new itowns.Coordinates(feature.crs, vertices[0], vertices[1], vertices[2]);

                    // set model position
                    model.position.copy(coord.xyz());

                    // set model orientation (using target parameter)
                    itowns.OrientationUtils.quaternionFromAttitude(feature.geometry[0].properties, coord, true, model.quaternion);

                    // store base position
                    model.positionBase = model.position.clone();

                    // compute position on the ground
                    coord = coord.as('EPSG:4326');
                    result = itowns.DEMUtils.getElevationValueAt(view.tileLayer, coord, 1, undefined);
                    coord.setAltitude(result.z);
                    model.positionOnGround = coord.as(view.referenceCrs).xyz();

                    // update matrix world and add the model
                    model.updateMatrixWorld();
                    view.scene.add(model);

                    // store the model
                    feature.model = model;

                    // Add cameras on the model
                    for(const cam of cameras) {

                        // add new cameras to the model
                        var camera = new itowns.OrientedImageCamera();
                        camera.copy(cam);
                        model.add(camera);
                        camera.updateMatrixWorld(true);

                        // add camera helper to the scene
                        var helper = new itowns.THREE.CameraHelper(camera);
                        view.scene.add(helper);
                        helper.updateMatrixWorld(true);
                    }
                }
                view.notifyChange();

                // store the features
                layer.features = points.features;
            }

            // add debug GUI
            var d = new debug.Debug(view, menuGlobe.gui);
            debug.createTileDebugUI(menuGlobe.gui, view, view.tileLayer, d);

            // Add a checkbox to put the cars on the ground.
            folder = menuGlobe.gui.addFolder('Cars Layer');
            folder.add(layer, 'onGround').onChange(function switchMode(/* value */) {
                for (const feature of layer.features) {
                    feature.model.position.copy(layer.onGround? feature.model.positionOnGround : feature.model.positionBase);
                    feature.model.updateMatrixWorld();
                }
                view.scene.updateMatrixWorld();
                view.notifyChange();
            });
        </script>
    </body>
</html>
